/**
 * @author Lukas Koell
 * @author David Medenjak
 * @author Johannes Riedmann
 */
public class Test {

    private static final String hr = "-----------------------------------------------------------------------------------------";

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) {

        startTest("Wie in der Angabe spezifiziert, gilt f�r Pfade im Baum die true(right)/false(left) Schreibweise");
        /*
         * 1. Erzeugen Sie je einen Baum der Typen ReplaceableTree<String>,
         * InorderTree<Integer>, PreorderTree<Student> und
         * PostorderTree<Professor> fügen Sie einige Instanzen der
         * entsprechenden Typen in beliebiger Reihenfolge ein, und geben Sie
         * alle Elemente (bei Personen inklusive Matrikelnummern bzw.
         * Instituten) in der Reihenfolge aus, in der sie vom durch iterator
         * erzeugten Iterator zur�ckgegeben werden. Suchen Sie auch �ber
         * contains und search nach jeweils einigen Elementen in den B�umen
         * und geben Sie alle Elemente der Teilb�ume unter den gefundenen
         * Knoten sowie die Pfade zu den gefundenen Knoten aus.
         */
        
        System.out.println(hr);
        System.out.println();
        System.out.println("Tests Teil 1 starten hier");
        System.out.println();
        System.out.println(hr);

        /* Testing replaceableTree... */
        startTest("creating a ReplaceableTree<String>");
        ReplaceableTree<String> rpl = new ReplaceableTree<String>();
        rpl.add("a first String");
        rpl.add("a second String");
        rpl.add("a third String");
        rpl.add("a fourth String");
        rpl.add("a fifth String");
        rpl.add("a sixth String");

        TreeIter<String> stringIter = rpl.iterator();

        while (stringIter.hasNext()) {
            System.out.println(stringIter.next().toString());
        }

        startTest("creating an InorderTree<Integer>");
        InorderTree<Integer> iot = new InorderTree<Integer>();
        iot.add(15);
        iot.add(12);
        iot.add(14);
        iot.add(13);
        iot.add(33);
        TreeIter<Integer> intIter = iot.iterator();
        while (intIter.hasNext()) {
            System.out.println(intIter.next().toString());
        }

        startTest("creating a PreorderTree<Student>");
        PreorderTree<Student> pot = new PreorderTree<Student>();
        pot.add(new Student("Dave Medenjak", 1234));
        pot.add(new Student("Johi Riedmann", 4567));
        pot.add(new Student("Luggi K�ll", 6789));
        TreeIter<Student> studIter = pot.iterator();

        while (studIter.hasNext()) {
            System.out.println(studIter.next().toString());
        }

        startTest("creating a PostorderTree<Professor>");
        PostorderTree<Professor> postot = new PostorderTree<Professor>();
        postot.add(new Professor("Michael Tannheimer", "E1234"));
        postot.add(new Professor("Peter Purgi", "E4567"));
        postot.add(new Professor("Robert Gunkl", "E6789"));
        TreeIter<Professor> profIter = postot.iterator();
        while (profIter.hasNext()) {
            System.out.println(profIter.next().toString());
        }

        /*
         * Suchen Sie auch über contains und search nach jeweils einigen
         * Elementen in den Bäumen und geben Sie alle Elemente der Teilbäume
         * unter den gefundenen Knoten sowie die Pfade zu den gefundenen Knoden
         * aus.
         */
        
        startTest("Testing contains() on the InorderTree<Integer>, this is the subtree of 14 (if found)");
      TreeIter<Integer> containsIt = iot.contains(14);
      while(containsIt.hasNext()){
          print(containsIt.next().toString());
      }
      

      startTest("Searching in the InorderTree<Integer>");
      Iter<Boolean> searchIter = iot.search(15);
      if (searchIter == null) {
          print("Item 15 was not found");
      } else {
          if (!searchIter.hasNext()) {
              print("Item 15 is in the root!");
          } else {
              print("Item 15 was found (this is not good), path:");
              while (searchIter.hasNext()) {
                  print(searchIter.next().toString());
              }
          }
      }
      searchIter = iot.search(14);
      if (searchIter == null) {
          print("Item 14 was not found (this is bad)");
      } else {
          print("Item 14 was found, path:");
          if (searchIter.hasNext()) {
              while (searchIter.hasNext()) {
                  print(searchIter.next().toString());
              }
          } else {
              print(searchIter.next().toString());
          }

      }
      
        startTest("searching Robert Gunkl by name in the ProfessorTree:");
        Iter<Boolean> profit = postot.search(new Professor("Robert Gunkl",
                "E1234"));
        if (profit != null) {
            print("Professor Gunkl found!");
            if(profit.hasNext()){
                print("This is the Path to him:");
                while (profit.hasNext()) {
                    System.out.println(profit.next());
                }
            }
        }

        /*
         * 2. Erzeugen Sie einen Baum vom Typ ReplaceableTree<Person> und fügen
         * Sie einige Instanzen von Student und Professor ein. Ersetzen Sie dann
         * zwei unterschiedliche Teilbäume des Baums durch die in Punkt 1
         * erzeugten Bäume der Typen PreorderTree<Student> und
         * PostorderTree<Professor>. Geben Sie über den Iterator den so
         * erzeugten Baum aus (nur die Namen der Personen), wobei Sie durch
         * Verwendung von down die Struktur des Baumes sichtbar werden lassen.
         */

        System.out.println(hr);
        System.out.println();
        System.out.println("Tests Teil 2 starten hier");
        System.out.println();
        System.out.println(hr);
        
        
        startTest("creating a ReplaceableTree<Person> and adding Students and Professors");
        ReplaceableTree<Person> rt = new ReplaceableTree<Person>();
        Student mrfoo = new Student("Mr. Foo", 4567);
        Professor captain = new Professor("Captain Brannigan", "E4567");
        rt.add(new Student("Dave Medenjak", 1234));
        rt.add(new Professor("Petri Purgfer", "E4567"));
        rt.add(mrfoo);
        rt.add(captain);
        TreeIter<Person> rtIt = rt.iterator();
        while(rtIt.hasNext()){
            System.out.println(rtIt.next());
        }

        startTest("replacing the PreorderTree<Student> into the node of Mr. Foo.");
        System.out.println("Now the Person-Tree contains:");
        rt.replace(rt.search(mrfoo), pot);
        TreeIter<Person> rep1It = rt.iterator();
        while (rep1It.hasNext()) {
            System.out.print(rep1It.next().toString() + ", ");
        }

        startTest("replacing the PostorderTree<Professor> into the node of Captain Brannigan. ");
        System.out.println("PreorderTree<Student> contains these nodes afterwards:");
        		
        rt.replace(rt.search(captain), postot);

        TreeIter<Person> it = rt.iterator();

        while (it.hasNext()) {
            System.out.println(it.next().toString());
        }

        startTest("Testing down() method, in the top layer you can see all subnodes of each node");
        TreeIter<Person> downIter = rt.iterator();

        // only go through root once
        while (downIter.hasNext()) {
            print(downIter.next().toString());
            TreeIter<Person> downIter2 = downIter.down();
            downIter2.next();
            if (downIter2 != null) {
                while (downIter2.hasNext()) {
                    print(" - " + downIter2.next().toString());
                }
            }
        }
        
        System.out.println(hr);
        System.out.println();
        System.out.println("Tests Teil 3 (eigene Tests) starten hier");
        System.out.println();
        System.out.println(hr);
        
        
        startTest("Creating a PreorderTree<Integer> with nodes 5, 6, 7, 9, 3, 4, 2.");
        print("This is the iteration (should be 5, 3, 2, 4, 6, 7, 9):");
        PreorderTree<Integer> preorderTree = new PreorderTree<Integer>();
        preorderTree.add(5);
        preorderTree.add(6);
        preorderTree.add(7);
        preorderTree.add(9);
        preorderTree.add(3);
        preorderTree.add(4);
        preorderTree.add(2);
        TreeIterator<Integer> preorderIt = preorderTree.iterator();
        while(preorderIt.hasNext()){
            print(preorderIt.next().toString());
        }
        
        startTest("Creating a PostorderTree<Integer> with nodes 5, 6, 7, 9, 3, 4, 2.");
        print("This is the iteration (should be 2, 4, 3, 9, 7, 6, 5) :");
        PostorderTree<Integer> postorderTree = new PostorderTree<Integer>();
        postorderTree.add(5);
        postorderTree.add(6);
        postorderTree.add(7);
        postorderTree.add(9);
        postorderTree.add(3);
        postorderTree.add(4);
        postorderTree.add(2);
        TreeIterator<Integer> postorderIt = postorderTree.iterator();
        while(postorderIt.hasNext()){
            print(postorderIt.next().toString());
        }
        
        startTest("Creating a InorderTree<Integer> with nodes 5, 6, 7, 9, 3, 4, 2.");
        print("This is the iteration (should be 2, 3, 4, 5, 6, 7, 9) :");
        InorderTree<Integer> inorderTree = new InorderTree<Integer>();
        inorderTree.add(5);
        inorderTree.add(6);
        inorderTree.add(7);
        inorderTree.add(9);
        inorderTree.add(3);
        inorderTree.add(4);
        inorderTree.add(2);
        TreeIterator<Integer> inorderIt = inorderTree.iterator();
        while(inorderIt.hasNext()){
            print(inorderIt.next().toString());
        }
        
    }

    static private void startTest(String comment) {
        System.out.println(hr);
        System.out.println(">>> " + comment);
    }

//    static private void test(String comment, Object output) {
//        System.out.println("> " + comment + "\n" + output);
//    }

    static private void print(String comment) {
        System.out.println("> " + comment);
    }
}
